package com.example.lib.threadlocal;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 类说明：ThreadLocal造成的内存泄漏演示
 * -Xms:初始堆大小
 * -Xmx:最大堆大小
 * -Xmx250m
 *
 * @author tk
 * @date 2020/9/29
 */
public class ThreadLocalOOM {

    /**
     * 任务循环次数
     */
    private static final int TASK_LOOP_SIZE = 500;

    /**
     * 线程工厂只要是起名
     */
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "me #" + mCount.getAndIncrement());
        }
    };

    /**
     * 5核心线程池
     */
    private final static ThreadPoolExecutor POOL_EXECUTOR
            = new ThreadPoolExecutor(5, 5, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(), sThreadFactory);

    /**
     * 5M大小
     */
    private static class LocalVariable1 {
        private byte[] a = new byte[5 * 1024 * 1024];
    }

    //
    private static ThreadLocal<LocalVariable1> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < TASK_LOOP_SIZE; i++) {
            POOL_EXECUTOR.execute(new Runnable() {
                @Override
                public void run() {
//                    new LocalVariable1();//不会产生内存泄漏

                    threadLocal.set(new LocalVariable1());//单独调用set会产生了内存泄漏  内存变化区间30-200M
//                    threadLocal.remove();//调用remove不会内存泄漏，内存不会超过50M

                    System.out.println("new LocalVarible" + Thread.currentThread().getName());
                }
            });

            Thread.sleep(100);
        }

        //循环一定次数后 o 会回收
//        Object o = new Object();
//        WeakReference<Object> weak = new WeakReference<Object>(o);
//        int i = 0;
//        while (true) {
//            if (weak.get() != null) {
//                i++;
//                System.out.println("Object is alive for " + i + " loops - " + weak);
//            } else {
//                System.out.println("Object has been collected.");
//                break;
//            }
//        }

        System.out.println("pool execute end");


    }

}
